#include <iostream>
#include <fstream>
#include <string>
#include <queue>

#include "ALU_MUL.h"
#include "ALU_DEF.h"
#include "ALU_ADD.h"
#include "LRF.h"
#include "ALU_CLUSTER.h"
#include "SRF.h"

#include "CImg.h"

using namespace std;

cimg_library::CImg<unsigned char> image( 128, 128, 1, 3);
unsigned char color[3];

typedef struct
{
    int opCode;
    int operand1;
    int operand2;
    int regDst;

	// Branch-specific fields
	int lrfEntry;
	int offset;
} ParsedInstruction;

vector<string> instructions;

typedef struct
{
	ParsedInstruction instructions[10];
} VLIWinstruction;

vector<VLIWinstruction> VLIWinstructions;

//#define PRINTDEBUG 0
#define DEFAULT_STREAM_SIZE 10
#define CLUSTER_COUNT 8
#define IMAGE_WIDTH 128
#define IMAGE_HEIGHT 128

int GetIntVal( string strConvert )
{
    return atoi( strConvert.c_str() );
}

ParsedInstruction instructionDecode( string instruction )
{
    ParsedInstruction result;
    result.opCode = NOP_OPCODE;

    int space1;
    int space2;
    int space3;
	int space4;
	int space5;
   
    string operand1;
    string operand2;
    string regDst;
    string temp;
	string lrfEntry;
	string offset;

    if ( NULL != strstr(instruction.c_str(), "IADDS"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an IADDS instruction.\n";
#endif
        result.opCode = IADDS_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if ( NULL != strstr(instruction.c_str(), "IADD"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an IADD instruction.\n";
#endif
        result.opCode = IADD_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "ISUBS"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an ISUBS instruction.\n";
#endif
        result.opCode = ISUBS_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "ISUB"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an ISUB instruction.\n";
#endif
        result.opCode = ISUB_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "IABD"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an IABD instruction.\n";
#endif
        result.opCode = IABD_OPCODE;   

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "UABD"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a UABD instruction.\n";
#endif
        result.opCode = UABD_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "ILT"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an ILT instruction.\n";
#endif
        result.opCode = ILT_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "ULT"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a ULT instruction.\n";
#endif
        result.opCode = ULT_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "ILE"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an ILE instruction.\n";
#endif
        result.opCode = ILE_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "ULE"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a ULE instruction.\n";
#endif
        result.opCode = ULE_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "IEQ"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an IEQ intstruction.\n";
#endif
        result.opCode = IEQ_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "NEQ"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an NEQ instruction.\n";
#endif
        result.opCode = NEQ_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "AND"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an AND instruction.\n";
#endif
        result.opCode = AND_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "XOR"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a XOR instruction.\n";
#endif
        result.opCode = XOR_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "OR"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an OR instruction.\n";
#endif
        result.opCode = OR_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "NOT"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a NOT instruction.\n";
#endif
        result.opCode = NOT_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "UADDS"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a UADDS instruction.\n";
#endif
        result.opCode = UADDS_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "USUBS"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a USUBS instruction.\n";
#endif
        result.opCode = USUBS_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "SHIFTA"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a SHIFTA instruction.\n";
#endif
        result.opCode = SHIFTA_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "SHIFT"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a SHIFT instruction.\n";
#endif
        result.opCode = SHIFT_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "ROTATE"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a ROTATE instruction.\n";
#endif
        result.opCode = ROTATE_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "FADD"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an FADD instruction.\n";
#endif
        result.opCode = FADD_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "FSUB"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an FSUB instruction.\n";
#endif
        result.opCode = FSUB_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "FABS"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an FABS instruction.\n";
#endif
        result.opCode = FABS_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "FLT"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an FLT instruction.\n";
#endif
        result.opCode = FLT_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "FLE"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an FLE instruction.\n";
#endif
        result.opCode = FLE_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "FTOI"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an FTOI instruction.\n";
#endif
        result.opCode = FTOI_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "FFRAC"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an FFRAC instruction.\n";
#endif
        result.opCode = FFRAC_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "ITOF"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an ITOF instruction.\n";
#endif
        result.opCode = ITOF_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "IDIVR"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an IDIVR instruction.\n";
#endif
        result.opCode = IDIVR_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "IDIV"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an IDIV instruction.\n";
#endif
        result.opCode = IDIV_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "UDIVR"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a UDIVR instruction.\n";
#endif
        result.opCode = UDIVR_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "UDIV"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a UDIV instruction.\n";
#endif
        result.opCode = UDIV_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "FDIV"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an FDIV instruction.\n";
#endif
        result.opCode = FDIV_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "FSQT"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an FSQT instruction.\n";
#endif
        result.opCode = FSQRT_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "IMULR"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an IMULR instruction.\n";
#endif
        result.opCode = IMULR_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "IMULD"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an IMULD instruction.\n";
#endif
        result.opCode = IMULD_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "IMUL"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an IMUL instruction.\n";
#endif
        result.opCode = IMUL_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "UMULR"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a UMULR instruction.\n";
#endif
        result.opCode = UMULR_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "UMULD"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a UMULD instruction.\n";
#endif
        result.opCode = UMULD_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "UMUL"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a UMUL instruction.\n";
#endif
        result.opCode = UMUL_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
    else if (NULL != strstr(instruction.c_str(), "FMUL"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an FMUL instruction.\n";
#endif
        result.opCode = FMUL_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
	else if ( NULL != strstr(instruction.c_str(), "DATA_IN"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a DATA_IN instruction.\n";
#endif
        result.opCode = DATA_IN_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, instruction.length() - space1 - space2 - space3 - 1);

        result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
    }
	else if ( NULL != strstr(instruction.c_str(), "DATA_OUT"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded a DATA_OUT instruction.\n";
#endif
        result.opCode = DATA_OUT_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, instruction.length() - space1 - space2 - space3 - 1);

        result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
    }
	else if ( NULL != strstr(instruction.c_str(), "BNE"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an BNE instruction.\n";
#endif
        result.opCode = BNE_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");
		temp = temp.substr(space4 + 1, temp.length() - space4 - 1);
		space5 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr(space1 + space2 + space3 + space4 + 4, space5);
		offset = instruction.substr(space1 + space2 + space3 + space4 + space5 + 5, instruction.length() - space1 - space2 - space3 - 1);


        result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
		result.offset = GetIntVal(offset);
    }
	else if ( NULL != strstr(instruction.c_str(), "BEQ"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an BEQ instruction.\n";
#endif
        result.opCode = BEQ_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");
		temp = temp.substr(space4 + 1, temp.length() - space4 - 1);
		space5 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr(space1 + space2 + space3 + space4 + 4, space5);
		offset = instruction.substr(space1 + space2 + space3 + space4 + space5 + 5, instruction.length() - space1 - space2 - space3 - 1);


        result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
		result.offset = GetIntVal(offset);
    }
	else if ( NULL != strstr(instruction.c_str(), "LI"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an LI instruction.\n";
#endif
        result.opCode = LI_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
        temp = temp.substr(space2 + 1, temp.length() - space2 - 1);
        space3 = temp.find_first_of(" ");
		temp = temp.substr(space3 + 1, temp.length() - space3 - 1);
		space4 = temp.find_first_of(" ");

        operand1 = instruction.substr(space1 + 1, space2);
        operand2 = instruction.substr(space1 + space2 + 2, space3);
        regDst = instruction.substr(space1 + space2 + space3 + 3, space4);
		lrfEntry = instruction.substr( space1 + space2 + space3 + 4, instruction.length() - space1 - space2 - space3 - space4 - 1 );

		result.operand1 = GetIntVal(operand1);
        result.operand2 = GetIntVal(operand2);
        result.regDst = GetIntVal(regDst);
		result.lrfEntry = GetIntVal(lrfEntry);
    }
	else if ( NULL != strstr(instruction.c_str(), "J"))
    {
#ifdef PRINTDEBUG
        cout << "We decoded an J instruction.\n";
#endif
        result.opCode = J_OPCODE;

        space1 = instruction.find_first_of(" ");
        temp = instruction.substr(space1 + 1, instruction.length() - space1);
        space2 = temp.find_first_of(" ");
     
        operand1 = instruction.substr(space1 + 1, space2);
        
		result.operand1 = GetIntVal(operand1);
    }
    else
    {
#ifdef PRINTDEBUG
        cout << "Parsed invalid instruction.\n";
#endif
    }

    return result;
}

bool processing(ALU_CLUSTER * cluster)
{
    bool ready = true;
   
    for(int i = 0; i < ALU_CLUSTER_ADD_SIZE; i++)
    {
        if(!cluster->isFinished(ALU_ADD_FU, i))
        {
            ready = false;
        }
    }
    for(int i = 0; i < ALU_CLUSTER_MUL_SIZE; i++)
    {
        if(!cluster->isFinished(ALU_MUL_FU, i))
        {
            ready = false;
        }
    }
    for(int i = 0; i < ALU_CLUSTER_DSQ_SIZE; i++)
    {
        if(!cluster->isReady(ALU_DSQ_FU, i))
        {
            ready = false;
        }
    }

    return !ready;
}

void srcToVLIW( void )
{
	// Set all parsed instructions opCodes to zero to initialize
	VLIWinstruction temp;
	ParsedInstruction currentInstruction;

	for ( int b = 0; b < 10; b++ )
	{
		temp.instructions[b].opCode = NOP_OPCODE;
	}

	for ( unsigned int a = 0; a < instructions.size(); a++ )
	{
		currentInstruction = instructionDecode( instructions[a] );

		if((currentInstruction.opCode >= 0 && currentInstruction.opCode <= 20) || (currentInstruction.opCode >= 31 && currentInstruction.opCode <= 38))
        {
			// ADD instructions
			if( 0 == currentInstruction.lrfEntry )
			{
				if (temp.instructions[0].opCode == NOP_OPCODE)
				{
					temp.instructions[0] = currentInstruction;
				}
				else
				{
					VLIWinstructions.push_back( temp );
					for ( int b = 0; b < 10; b++ )
					{
						temp.instructions[b].opCode = NOP_OPCODE;
					}
					temp.instructions[0] = currentInstruction;
				}
			}
			else if ( 1 == currentInstruction.lrfEntry )
			{
				if (temp.instructions[1].opCode == NOP_OPCODE)
				{
					temp.instructions[1] = currentInstruction;
				}
				else
				{
					VLIWinstructions.push_back( temp );
					for ( int b = 0; b < 10; b++ )
					{
						temp.instructions[b].opCode = NOP_OPCODE;
					}
					temp.instructions[1] = currentInstruction;
				}
			}
			else if ( 2 == currentInstruction.lrfEntry )
			{
				if (temp.instructions[2].opCode == NOP_OPCODE)
				{
					temp.instructions[2] = currentInstruction;
				}
				else
				{
					VLIWinstructions.push_back( temp );
					for ( int b = 0; b < 10; b++ )
					{
						temp.instructions[b].opCode = NOP_OPCODE;
					}
					temp.instructions[2] = currentInstruction;
				}
			}
		}
		else if((currentInstruction.opCode >= 21 && currentInstruction.opCode <= 26) || (currentInstruction.opCode == 39))
        {
			// MUL instructions
			if( 0 == currentInstruction.lrfEntry )
			{
				if (temp.instructions[3].opCode == NOP_OPCODE)
				{
					temp.instructions[3] = currentInstruction;
				}
				else
				{
					VLIWinstructions.push_back( temp );
					for ( int b = 0; b < 10; b++ )
					{
						temp.instructions[b].opCode = NOP_OPCODE;
					}
					temp.instructions[3] = currentInstruction;
				}
			}
			else if ( 1 == currentInstruction.lrfEntry )
			{
				if (temp.instructions[4].opCode == NOP_OPCODE)
				{
					temp.instructions[4] = currentInstruction;
				}
				else
				{
					VLIWinstructions.push_back( temp );
					for ( int b = 0; b < 10; b++ )
					{
						temp.instructions[b].opCode = NOP_OPCODE;
					}
					temp.instructions[4] = currentInstruction;
				}
			}
		}
		else if((currentInstruction.opCode >= 27 && currentInstruction.opCode <= 30) || (currentInstruction.opCode >= 40 && currentInstruction.opCode <= 41))
        {
			// DIV instructions
			if( 0 == currentInstruction.lrfEntry )
			{
				if (temp.instructions[5].opCode == NOP_OPCODE)
				{
					temp.instructions[5] = currentInstruction;
				}
				else
				{
					VLIWinstructions.push_back( temp );
					for ( int b = 0; b < 10; b++ )
					{
						temp.instructions[b].opCode = NOP_OPCODE;
					}
					temp.instructions[5] = currentInstruction;
				}
			}
		}
		else if( 42 == currentInstruction.opCode )
		{
			// DATA_IN instruction

			if (temp.instructions[6].opCode == NOP_OPCODE)
			{
				temp.instructions[6] = currentInstruction;
			}
			else
			{
				VLIWinstructions.push_back( temp );
				for ( int b = 0; b < 10; b++ )
				{
					temp.instructions[b].opCode = NOP_OPCODE;
				}
				temp.instructions[6] = currentInstruction;
			}
		}
		else if( 43 == currentInstruction.opCode )
		{
			// DATA_OUT instruction
			if (temp.instructions[7].opCode == NOP_OPCODE)
			{
				temp.instructions[7] = currentInstruction;
			}
			else
			{
				VLIWinstructions.push_back( temp );
				for ( int b = 0; b < 10; b++ )
				{
					temp.instructions[b].opCode = NOP_OPCODE;
				}
				temp.instructions[7] = currentInstruction;
			}
		}
		else if( currentInstruction.opCode >= 44 && currentInstruction.opCode <= 46 )
		{
			// J/BR instructions
			if (temp.instructions[8].opCode == NOP_OPCODE)
			{
				temp.instructions[8] = currentInstruction;
			}
			else
			{
				VLIWinstructions.push_back( temp );
				for ( int b = 0; b < 10; b++ )
				{
					temp.instructions[b].opCode = NOP_OPCODE;
				}
				temp.instructions[8] = currentInstruction;
			}
		}
		else if( 47 == currentInstruction.opCode )
		{
			// LI instruction
			if (temp.instructions[9].opCode == NOP_OPCODE)
			{
				temp.instructions[9] = currentInstruction;
			}
			else
			{
				VLIWinstructions.push_back( temp );
				for ( int b = 0; b < 10; b++ )
				{
					temp.instructions[b].opCode = NOP_OPCODE;
				}
				temp.instructions[9] = currentInstruction;
			}
		}
	}

	VLIWinstructions.push_back( temp );
}
int main(void)
{
    // Start clock cycle count at zero
    int clockCycles = 0;

	// Initialize program counter (PC) to zero
	unsigned int PC = 0;

	// Create place to store operands read from LRFs
	int operand1 = 0;
	int operand2 = 0;
   
    // Open up code file and store instructions in vector
    ifstream       microcode("code.imn");
    string         tempString;

    if( microcode.is_open())
    {
        while( !microcode.eof())
        {
            getline(microcode, tempString);
            instructions.push_back(tempString);
        }

        microcode.close();
    }

    ParsedInstruction currentInstruction;

    // Initialize clusters and Local Register Files
    ALU_CLUSTER* myCluster[CLUSTER_COUNT];

	for( int c = 0; c < CLUSTER_COUNT; c++ )
	{
		myCluster[c] = new ALU_CLUSTER();
	}

	// Initialize SRF with image values
	SRF * mySRF = new SRF();

	ifstream picture("Book1.csv");

	unsigned char test_init[IMAGE_WIDTH*IMAGE_HEIGHT];
	
	int counter = 0;

	char token[DEFAULT_STREAM_SIZE];

	for ( int t = 0; t < IMAGE_HEIGHT; t++)
	{
		for( int s = 0; s < IMAGE_WIDTH; s++)
		{
			if (s == IMAGE_WIDTH - 1 )
			{
				picture.get(token, DEFAULT_STREAM_SIZE, '\n');
				picture.ignore( 1, '\n' );
			}
			else
			{
				picture.get(token, DEFAULT_STREAM_SIZE, ',');
				picture.ignore( 1, ',' );
			}
			test_init[counter] = GetIntVal(token);
			
			color[0] = test_init[counter];
			color[1] = test_init[counter];
			color[2] = test_init[counter];

			counter++;

			image.draw_point(s, t, color );
		}
	}

	cimg_library::CImgDisplay main( image, "Input" );

	mySRF->init_data_in(test_init, IMAGE_WIDTH * IMAGE_HEIGHT);

	// Now that we are supporting VLIW, I need to collect all of the normal ParsedInstructions into VLIWInstructions.
	srcToVLIW();

    // Continue processing while there are still instructions or busy units
    while( PC < VLIWinstructions.size() || processing(myCluster[0]))
    {
        if(PC < VLIWinstructions.size())
        {
			for (int c = 0; c < 10; c++)
			{
				currentInstruction = VLIWinstructions[PC].instructions[c];

				if((VLIWinstructions[PC].instructions[c].opCode >= 0 && VLIWinstructions[PC].instructions[c].opCode <= 20) || (VLIWinstructions[PC].instructions[c].opCode >= 31 && VLIWinstructions[PC].instructions[c].opCode <= 38))
				{
					bool issued = false;
					
					for ( int d = 0; d < 8; d++ )
					{
						myCluster[d]->get_lrf(ALU_ADD_FU, currentInstruction.lrfEntry, currentInstruction.operand1, (unsigned char &) operand1);
						myCluster[d]->get_lrf(ALU_ADD_FU, currentInstruction.lrfEntry, currentInstruction.operand2, (unsigned char &) operand2);
						myCluster[d]->set_fu(ALU_ADD_FU, currentInstruction.lrfEntry, operand1, 0.0f, operand2, 0.0f, currentInstruction.opCode, currentInstruction.regDst);
					}
				}
				else if((VLIWinstructions[PC].instructions[c].opCode >= 21 && VLIWinstructions[PC].instructions[c].opCode <= 26) || (VLIWinstructions[PC].instructions[c].opCode == 39))
				{
					for ( int e = 0; e < 8; e++ )
					{
						myCluster[e]->get_lrf(ALU_MUL_FU, currentInstruction.lrfEntry, currentInstruction.operand1, (unsigned char &) operand1);
						myCluster[e]->get_lrf(ALU_MUL_FU, currentInstruction.lrfEntry, currentInstruction.operand2, (unsigned char &) operand2);
						myCluster[e]->set_fu(ALU_MUL_FU, currentInstruction.lrfEntry, operand1, 0.0f, operand2, 0.0f, currentInstruction.opCode, currentInstruction.regDst);
					}
				}
				else if((VLIWinstructions[PC].instructions[c].opCode >= 27 && VLIWinstructions[PC].instructions[c].opCode <= 30) || (VLIWinstructions[PC].instructions[c].opCode >= 40 && VLIWinstructions[PC].instructions[c].opCode <= 41))
				{
					bool issued = false;
					for(int i = 0; i < ALU_CLUSTER_DSQ_SIZE; i++)
					{
						if(!issued)
						{
							if(myCluster[0]->isReady(ALU_DSQ_FU, i))
							{
								for ( int f = 0; f < 8; f++ )
								{
									myCluster[f]->get_lrf(ALU_DSQ_FU, i, currentInstruction.operand1, (unsigned char &) operand1);
									myCluster[f]->get_lrf(ALU_DSQ_FU, i, currentInstruction.operand2, (unsigned char &) operand2);
									myCluster[f]->set_fu(ALU_DSQ_FU, i, operand1, 0.0f, operand2, 0.0f, currentInstruction.opCode, currentInstruction.regDst);
								}
								issued = true;
							}
						}
					}
				}
				else if( 42 == VLIWinstructions[PC].instructions[c].opCode )
				{
					LRF * lrfGroup[8];

					for ( int a = 0; a < 8; a++)
					{
						lrfGroup[a] = myCluster[a]->get_lrf(currentInstruction.operand1, currentInstruction.operand2);
					}

					mySRF->data_in( lrfGroup, currentInstruction.regDst );
				}
				else if( 43 == VLIWinstructions[PC].instructions[c].opCode )
				{
					LRF * lrfGroup[8];

					for ( int b = 0; b < 8; b++)
					{
						lrfGroup[b] = myCluster[b]->get_lrf(currentInstruction.operand1, currentInstruction.operand2);
					}

					mySRF->data_out( lrfGroup, currentInstruction.regDst );
				}
				else if( 44 == VLIWinstructions[PC].instructions[c].opCode )
				{
					int temp;

					myCluster[currentInstruction.operand1]->get_lrf( currentInstruction.operand1, currentInstruction.operand2, currentInstruction.regDst, temp );
					if( 0 == temp )
					{
						PC = PC + currentInstruction.offset;
					}
				}
				else if ( 45 == VLIWinstructions[PC].instructions[c].opCode )
				{
					int temp;

					myCluster[currentInstruction.operand1]->get_lrf( currentInstruction.operand1, currentInstruction.operand2, currentInstruction.regDst, temp );
					if( 0 != temp )
					{
						PC = PC + currentInstruction.offset;
					}
				}
				else if ( 46 == VLIWinstructions[PC].instructions[c].opCode )
				{
					PC = PC + currentInstruction.operand1;
				}
				else if ( 47 == VLIWinstructions[PC].instructions[c].opCode )
				{
					for ( int j = 0; j < 8; j++ )
					{
						myCluster[j]->set_lrf( currentInstruction.operand1, currentInstruction.operand2, 
											   currentInstruction.regDst,   (unsigned char) currentInstruction.lrfEntry );
					}
				}
				else if(currentInstruction.opCode < 0 && instructions.size() > 0)
				{
					// Invalid instruction, discard
				}
			}
           
        }
        else
        {
            currentInstruction.opCode = NOP_OPCODE;
        }

		for( int k = 0; k < 8; k++ )
		{
			for(int i = 0; i < ALU_CLUSTER_ADD_SIZE; i++)
			{
				myCluster[k]->update(ALU_ADD_FU, i);
			}
			for(int i = 0; i < ALU_CLUSTER_MUL_SIZE; i++)
			{
				myCluster[k]->update(ALU_MUL_FU, i);
			}
			for(int i = 0; i < ALU_CLUSTER_DSQ_SIZE; i++)
			{
				myCluster[k]->update(ALU_DSQ_FU, i);
			}
		}

		PC++;

        clockCycles++;       
    }

    cout << "Simulation complete: " << clockCycles << " cycles.\n";

	// Copy and display results from SRF
	unsigned char output[IMAGE_WIDTH*IMAGE_HEIGHT];

	mySRF->get_data_out( output, IMAGE_WIDTH*IMAGE_HEIGHT );

	counter = 0;

	for ( int t = 0; t < IMAGE_HEIGHT; t++)
	{
		for( int s = 0; s < IMAGE_WIDTH; s++)
		{
			color[0] = output[counter];
			color[1] = output[counter];
			color[2] = output[counter];

			counter++;

			image.draw_point(s, t, color );
		}
	}

	cimg_library::CImgDisplay main2( image, "Result" );

	while( !main.is_closed() || !main2.is_closed() )
	{
		main.wait();
	}	

    return 0;
}
